#include "TokenSenCtrl.h"
#include "TokenBlock.h"
#include "TokenBoolExp.h"
#include "Error.h"
#include <string>
#include <sstream>
#include <iostream> // for clog
using namespace std;
void TokenSenIf::run(bool enabled /*= true*/)
{
	//clog << "IF" << endl;
	int start = string("if").size();
	assert(toParse.substr(0, start) == "if");
	int ifPos = toParse.find("if");
	assert(ifPos != string::npos);
	int colPos = toParse.find(":");
	if (colPos == string::npos)
		throw Error("Colon expected after \"if\".");
	if (start >= toParse.size())
		throw Error("Nothing after \"if\".");
	else if (toParse[start] != ' ' && toParse[start] != '\t')
		throw Error("Space expected after \"if\"."); // Never!!!
	istringstream sin(toParse.substr(colPos+1, toParse.size()-(colPos+1)));
	string word;
	sin >> word;
	if (word != "")
		throw Error("Unexpected \"" + word + "\" after colon.");
	TokenBoolExp tbe(toParse.substr(ifPos+start+1, colPos-(ifPos+start+1)));
	TokenBlock tb;
	bool con = tbe.getResult();
	tb.run(enabled && con);

	Context* ctx = Context::getInstance();
	
	string line;
	int ind;
	do
	{
		line = ctx -> nextLine(); // indent was not removed by TokenBlock
		ind = 0;
		while (ind < line.size() &&
			(line[ind] == ' ' || line[ind] == '\t')
			) ind ++;
	} while (ind >= line.size());
	string indentCur = ctx -> indent.back();
	if (ind > indentCur.size())
		throw Error("Unexpected indent.");
	else if (ind < indentCur.size())
		ctx -> rollbackLine();
	else
	{
		if (indentCur != line.substr(0, indentCur.size()))
			throw Error("Mix tab and space.");
		toParse = line.substr(ind, line.size()-ind);
		start = string("else").size();
		if (toParse.substr(0, start) == "else")
		{
			//clog << "ELSE" << endl;
			sin.clear();
			sin.str(toParse.substr(start, toParse.size()-start));
			sin >> word;
			if (word != ":")
				throw Error("Colon expected after \"else\".");
			sin >> word;
			if (sin)
				throw Error("Unexpected " + word + " after colon.");
			tb.run(enabled && !con);
		}
		else
			ctx -> rollbackLine();
	}
	//clog << "END_IF" << endl;
}
void TokenSenWhile::run(bool enabled /*= true*/)
{
	int start = string("while").size();
	assert(toParse.substr(0, start) == "while");
	int whilePos = toParse.find("while");
	assert(whilePos != string::npos);
	int colPos = toParse.find(":");
	if (colPos == string::npos)
		throw Error("Colon expected after \"while\".");
	if (start >= toParse.size())
		throw Error("Nothing after \"while\".");
	else if (toParse[start] != ' ' && toParse[start] != '\t')
		throw Error("Space expected after \"while\"."); // Never!!!
	istringstream sin(toParse.substr(colPos+1, toParse.size()-(colPos+1)));
	string word;
	sin >> word;
	if (word != "")
		throw Error("Unexpected " + word + " after colon.");
	TokenBoolExp tbe(toParse.substr(whilePos+start+1, colPos-(whilePos+start+1)));
	TokenBlock tb;
	Context* ctx = Context::getInstance();
	int beginPos = ctx -> getRow(); // regardless of empty line; should not +1 because it will be done in nextLine() automaticlly
	bool con = tbe.getResult();
	bool flagBreak = false;
	do
	{
		try
		{
			//clog << "LOOPING FROM " << beginPos << endl;
			enabled = enabled && (!flagBreak);
			//clog << enabled << con << flagBreak << endl;
			ctx -> setRow(beginPos);
			tb.run(enabled && con);
			//clog << "LOOPING END" << endl;
		}
		catch (ErrorBreak& eb)
		{
			//clog << "LOOPING BREAKED" << endl;
			flagBreak = true;
		}
	} while (enabled && (con = tbe.getResult(true))); // true force the BoolExp to calc again;
}

